import { useCallback, useState } from 'react';
import { useSetState, useUpdateEffect } from 'ahooks';
import {
  store_icon,
  shop_icon,
  bounds,
  formatValue,
  getClosestMultipleOfFour,
  divideValueIntoIntervals,
  findIntervalIndex,
} from '@/utils/marketingMap/utils';
import useHeatMap from '@/utils/marketingMap/useHeatMap';

interface StoreProps {
  lon: string;
  lat: string;
  code: string;
  name: string;
  vehicleCount: number;
  aftersalesCount: number;
  recentYearVehicleCount: number;
}

const content = (data: Omit<StoreProps, 'lon' | 'lat'>) => `
  <div class="title">${data.name}</div>
  <div class="item">售后车辆<span class="text">${formatValue(data.vehicleCount)}</span>台</div>
  <div class="item">售后车次<span class="text">${formatValue(data.aftersalesCount)}</span>次</div>
  <div class="item">近1年有效保客数<span class="text">${formatValue(
    data.recentYearVehicleCount,
  )}</span>台</div>
`;

const contentText = (name: string, count: number, type: string) => `
  <div class="title">${name}<span style="font-size: 12px;padding-left: 6px;">(近一年)</span></div>
  <div class="item">${type}<span class="text">${formatValue(count)}</span>台</div>
`;

const zoom = 14.5;

const useMap = (data: any, areaRange: number, isAuth: boolean) => {
  const [status, setStatus] = useState(true);
  const [state, setState] = useSetState<any>({});
  const { map, AMap, circle, layer, infoWindow, overlayGroup } = state;
  const { heatMap, setHeatMapData } = useHeatMap(AMap, map);

  const markerClick = (content: string, position: any) => {
    infoWindow.setContent(content);
    infoWindow.open(map, position);
  };

  const onRenderingCompleted = (map: any, AMap: any) => {
    const circle = new AMap.Circle({
      fillColor: '#1890ff',
      fillOpacity: 0.05,
      strokeWeight: 0,
    });

    const layer = new AMap.LabelsLayer({
      zooms: [3, 20],
      zIndex: 999999,
      collision: false,
    });

    const infoWindow = new AMap.InfoWindow({
      offset: new AMap.Pixel(0, -20),
      closeWhenClickMap: true,
      autoMove: true,
    });

    const overlayGroup = new AMap.OverlayGroup();

    map.add(circle, infoWindow, overlayGroup);

    setState({ map, AMap, circle, layer, infoWindow, overlayGroup });
  };

  const zoomMin = useCallback(
    (
      stores: any[],
      heatmaps: Pick<StoreProps, 'lon' | 'lat' | 'vehicleCount'>[],
      areaRange: number,
    ) => {
      const myStore = stores[0];

      if (!myStore) return setHeatMapData([]);

      overlayGroup.hide();
      circle.setCenter([myStore.lon, myStore.lat]);
      circle.setRadius(areaRange * 1000);

      const heatMapData = heatmaps.map(
        (item: Pick<StoreProps, 'lon' | 'lat' | 'vehicleCount'>) => ({
          lng: item.lon,
          lat: item.lat,
          count: item.vehicleCount,
        }),
      );

      setHeatMapData(heatMapData);

      circle.show();
      heatMap.show();
    },
    [heatMap, isAuth],
  );

  const zoomMax = useCallback(
    (gridmap: any[]) => {
      setHeatMapData([]);
      overlayGroup.clearOverlays();

      const max = gridmap.reduce((max, item) => {
        const currentMax = Math.max(item.ourCount, item.bothCount, item.otherCount, item.noneCount);
        return Math.max(max, currentMax);
      }, -Infinity);

      const interval = divideValueIntoIntervals(getClosestMultipleOfFour(max));
      const markers: any[] = gridmap.map((item: any) => {
        const { ourCount, bothCount, otherCount, noneCount } = item;
        const { sw, ne } = bounds(item.geo);
        const rectangles = [];

        if (ourCount) {
          const rectangle = new AMap.Rectangle({
            fillColor: '#1890ff',
            strokeColor: '#fff',
            strokeOpacity: 0.8,
            fillOpacity: findIntervalIndex(item.ourCount, interval) * 0.2 + 0.2,
            bounds: new AMap.Bounds(
              new AMap.LngLat(item.geoLon, ne.lat),
              new AMap.LngLat(sw.lng, item.geoLat),
            ),
          });
          rectangle.on('click', (e: any) => {
            markerClick(contentText(item.name, item.ourCount, '仅回本店售后'), [
              (item.geoLon + sw.lng) / 2,
              (item.geoLat + ne.lat) / 2,
            ]);
          });
          rectangles.push(rectangle);
        }
        if (bothCount) {
          const rectangle = new AMap.Rectangle({
            fillColor: '#4dcb73',
            strokeColor: '#fff',
            strokeOpacity: 0.8,
            fillOpacity: findIntervalIndex(item.bothCount, interval) * 0.2 + 0.2,
            bounds: new AMap.Bounds(
              new AMap.LngLat(item.geoLon, item.geoLat),
              new AMap.LngLat(ne.lng, ne.lat),
            ),
          });
          rectangle.on('click', (e: any) => {
            markerClick(contentText(item.name, item.bothCount, '回本店和其他售后店'), [
              (item.geoLon + ne.lng) / 2,
              (item.geoLat + ne.lat) / 2,
            ]);
          });
          rectangles.push(rectangle);
        }
        if (otherCount) {
          const rectangle = new AMap.Rectangle({
            fillColor: '#ff922e',
            strokeColor: '#fff',
            strokeOpacity: 0.8,
            fillOpacity: findIntervalIndex(item.otherCount, interval) * 0.2 + 0.2,
            bounds: new AMap.Bounds(
              new AMap.LngLat(item.geoLon, item.geoLat),
              new AMap.LngLat(sw.lng, sw.lat),
            ),
          });
          rectangle.on('click', (e: any) => {
            markerClick(contentText(item.name, item.otherCount, '仅在其他店售后'), [
              (item.geoLon + sw.lng) / 2,
              (item.geoLat + sw.lat) / 2,
            ]);
          });
          rectangles.push(rectangle);
        }
        if (noneCount) {
          const rectangle = new AMap.Rectangle({
            fillColor: '#ff594c',
            strokeColor: '#fff',
            strokeOpacity: 0.8,
            fillOpacity: findIntervalIndex(item.noneCount, interval) * 0.2 + 0.2,
            bounds: new AMap.Bounds(
              new AMap.LngLat(ne.lng, item.geoLat),
              new AMap.LngLat(item.geoLon, sw.lat),
            ),
          });
          rectangle.on('click', (e: any) => {
            markerClick(contentText(item.name, item.noneCount, '未回厂售后'), [
              (item.geoLon + ne.lng) / 2,
              (item.geoLat + sw.lat) / 2,
            ]);
          });
          rectangles.push(rectangle);
        }

        return rectangles;
      });

      overlayGroup.addOverlays(markers.flat());

      map.add(overlayGroup);

      circle.hide();
      // layer.hide();
      setState({ overlayGroup });
    },
    [heatMap],
  );

  useUpdateEffect(() => {
    if (heatMap && map) {
      map.clearMap();
      map.add([circle, layer, infoWindow, overlayGroup]);
      const [heatmaps, gridmap, stores] = data || [];
      const distributionData = stores?.distributionData;

      if (distributionData?.[0]) {
        layer.clear();

        const data = [...distributionData];

        const store = data.shift();

        const labelMarkers = data.map((item: StoreProps) => {
          const labelMarker = new AMap.LabelMarker({
            position: [item.lon, item.lat],
            icon: shop_icon,
          });

          labelMarker.on('mouseover', (e: any) =>
            markerClick(content(item), e.target.getPosition()),
          );

          return labelMarker;
        });

        const labelMarker = new AMap.LabelMarker({
          position: [store.lon, store.lat],
          icon: store_icon,
          zIndex: 100,
        });

        labelMarker.on('mouseover', (e: any) =>
          markerClick(content(store), e.target.getPosition()),
        );

        markerClick(content(store), [store.lon, store.lat]);
        layer.add([...labelMarkers, labelMarker]);
        map.setCenter([store.lon, store.lat]);

        if (map.getZoom() < zoom) {
          zoomMin(distributionData, heatmaps, areaRange);
        } else {
          zoomMax(gridmap);
        }
      } else {
        infoWindow.close();
        map?.clearMap();
        setHeatMapData([]);
      }
    }
  }, [data, map, heatMap]);

  useUpdateEffect(() => {
    if (heatMap) {
      map.on('zoomend', () => {
        if (map.getZoom() < zoom) {
          setStatus(true);
        } else {
          setStatus(false);
        }
      });
    }
  }, [heatMap]);

  useUpdateEffect(() => {
    const [heatmaps, gridmap, stores] = data;
    const distributionData = stores.distributionData;

    if (status) {
      zoomMin(distributionData, heatmaps, areaRange);
    } else {
      zoomMax(gridmap);
    }
  }, [status]);

  return { status, map, markerClick, onRenderingCompleted };
};

export default useMap;
